package com.itheima.stock.job.impl;

import com.google.common.collect.Lists;
import com.itheima.stock.common.domain.StockInfoConfig;
import com.itheima.stock.mapper.StockBlockRtInfoMapper;
import com.itheima.stock.mapper.StockBusinessMapper;
import com.itheima.stock.mapper.StockMarketIndexInfoMapper;
import com.itheima.stock.mapper.StockRtInfoMapper;
import com.itheima.stock.pojo.StockBlockRtInfo;
import com.itheima.stock.pojo.StockMarketIndexInfo;
import com.itheima.stock.job.StockTimerTaskService;
import com.itheima.stock.pojo.StockRtInfo;
import com.itheima.stock.utils.DateTimeUtil;
import com.itheima.stock.utils.IdWorker;
import com.itheima.stock.utils.ParserStockInfoUtil;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class StockTimerTaskServiceImpl implements StockTimerTaskService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private StockInfoConfig stockInfoConfig;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private StockMarketIndexInfoMapper stockMarketIndexInfoMapper;

    @Autowired
    private ParserStockInfoUtil parserStockInfoUtil;

    @Autowired
    private StockBusinessMapper stockBusinessMapper;

    @Autowired
    private StockRtInfoMapper stockRtInfoMapper;

    @Autowired
    private StockBlockRtInfoMapper stockBlockRtInfoMapper;

    /**
     * 注入线程池对象
     */
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Override
    public void getInnerMarketInfo() {
        //1.获取远程服务器地址
        // http://hq.sinajs.cn/list=
        String marketUrl = stockInfoConfig.getMarketUrl();
        //2.获取大盘标记
        // s_sh000001  s_sz399001
        List<String> inner = stockInfoConfig.getInner();
        //3.拼接请求路径
        // http://hq.sinajs.cn/list=s_sh000001,s_sz399001
        String url = marketUrl+String.join(",",inner);
        //4.调用RestTemplate发送请求
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","http://finance.sina.com.cn");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36");
        // 准备请求实体对象,此对象中封装了请求携带的所有数据信息
        HttpEntity<Map> httpEntity = new HttpEntity<>(headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        //5.解析响应结果信息
        String result = response.getBody();
        System.out.println(result);
        // 定义正则表达式
        String reg="var hq_str_(.+)=\"(.+)\";";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(result);
        //收集大盘封装后后的对象
        ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
        while (matcher.find()) {
            //获取大盘的id
            String marketCode = matcher.group(1);
            System.out.println(marketCode);
            //其它信息
            String other = matcher.group(2);
            String[] others = other.split(",");
            //大盘名称
            String marketName=others[0];
            //当前点
            BigDecimal curPoint=new BigDecimal(others[1]);
            //当前价格
            BigDecimal curPrice=new BigDecimal(others[2]);
            //涨跌率
            BigDecimal upDownRate=new BigDecimal(others[3]);
            //成交量
            Long tradeAmount=Long.valueOf(others[4]);
            //成交金额
            Long tradeVol=Long.valueOf(others[5]);
            //当前日期
            Date now = DateTimeUtil.getDateTimeWithoutSecond(DateTime.now()).toDate();
            //封装对象
            StockMarketIndexInfo stockMarketIndexInfo = StockMarketIndexInfo.builder()
                    .id(idWorker.nextId()+"")
                    .markName(marketName)
                    .tradeVolume(tradeVol)
                    .tradeAccount(tradeAmount)
                    .updownRate(upDownRate)
                    .curTime(now)
                    .curPoint(curPoint)
                    .currentPrice(curPrice)
                    .markId(marketCode)
                    .build();
            list.add(stockMarketIndexInfo);
        };
        //批量插入
        if (CollectionUtils.isEmpty(list)) {
            log.info("");
            return;
        }
        // lombok注解提供的日志打印
        log.info("集合长度：{}，内容：{}",list.size(),list);
        // 将拉取的数据添加到数据库中
        stockMarketIndexInfoMapper.insertBatch(list);
        String curTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
        log.info("采集的大盘数据：{},当前时间：{}",list,curTime);
    }

    @Override
    public void getOuterMarketInfo() {
        //1.获取远程服务器地址
        // http://hq.sinajs.cn/list=
        String marketUrl = stockInfoConfig.getMarketUrl();
        //2.获取国外大盘标记
        List<String> outer = stockInfoConfig.getOuter();
        //3.拼接请求路径
        String url = marketUrl+String.join(",",outer);
        //4.调用RestTemplate发送请求
        // 创建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","http://finance.sina.com.cn");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36");
        // 准备请求实体对象,此对象中封装了请求携带的所有数据信息
        HttpEntity<Map> httpEntity = new HttpEntity<>(headers);
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        //5.解析响应结果信息
        String result = response.getBody();
        System.out.println(result);
        // 定义正则表达式
        String reg="var hq_str_(.+)=\"(.+)\";";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(result);
        //收集大盘封装后后的对象
        ArrayList<StockMarketIndexInfo> list = new ArrayList<>();
        while (matcher.find()) {
            //获取大盘的id
            String marketCode = matcher.group(1);
            System.out.println(marketCode);
            //其它信息
            String other = matcher.group(2);
            String[] others = other.split(",");
            //大盘名称
            String marketName=others[0];
            //当前点
            BigDecimal curPoint=new BigDecimal(others[1]);
            //当前价格
            BigDecimal curPrice=new BigDecimal(others[2]);
            //涨跌率
            BigDecimal upDownRate=new BigDecimal(others[3]);
            //当前日期
            Date now = DateTimeUtil.getDateTimeWithoutSecond(DateTime.now()).toDate();
            //封装对象
            StockMarketIndexInfo stockMarketIndexInfo = StockMarketIndexInfo.builder()
                    .id(idWorker.nextId()+"")
                    .markName(marketName)
                    .updownRate(upDownRate)
                    .curTime(now)
                    .curPoint(curPoint)
                    .currentPrice(curPrice)
                    .markId(marketCode)
                    .build();
            list.add(stockMarketIndexInfo);
        };
        //批量插入
        if (CollectionUtils.isEmpty(list)) {
            log.info("");
            return;
        }
        // lombok注解提供的日志打印
        log.info("集合长度：{}，内容：{}",list.size(),list);
        // 将拉取的数据添加到数据库中
        stockMarketIndexInfoMapper.insertBatch(list);
        String curTime = DateTime.now().toString(DateTimeFormat.forPattern("yyyyMMddHHmmss"));
        log.info("采集的大盘数据：{},当前时间：{}",list,curTime);
    }

    @Override
    public void getStockRtIndex() {
        //1.获取所有股票的id
        List<String> stockIds = stockBusinessMapper.getStockIds();//40--->3000
        //深证：A：以0开头 上证：6开头
        stockIds = stockIds.stream().map(id -> {
            id = id.startsWith("6") ? "sh" + id : "sz" + id;
            return id;
        }).collect(Collectors.toList());
        //设置请求头数据
        HttpHeaders headers = new HttpHeaders();
        headers.add("Referer","https://finance.sina.com.cn/stock/");
        headers.add("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36");
        HttpEntity<String> entity = new HttpEntity<>(headers);

        //要求：将集合分组，每组的集合长度为20
        Lists.partition(stockIds,20).forEach(ids->{
            //每个分片的数据开启一个线程异步执行任务
            threadPoolTaskExecutor.execute(()->{
                //拼接获取A股信息的url地址
                String stockRtUrl=stockInfoConfig.getMarketUrl()+String.join(",",ids);
                //发送请求获取数据
//               String result = restTemplate.getForObject(stockRtUrl, String.class);
                String result=restTemplate.postForObject(stockRtUrl,entity,String.class);
                //解析获取股票数据
                List<StockRtInfo> list = parserStockInfoUtil.parser4StockOrMarketInfo(result, 3);
                //分批次批量插入
                log.info("当前股票数据：{}",list);
                stockRtInfoMapper.insertBatch(list);
            });
        });
    }

    @Override
    public void getStockSectorRtIndex() {
        //发送板块数据请求
        String result = restTemplate.getForObject(stockInfoConfig.getBlockUrl(), String.class);
        //响应结果转板块集合数据
        List<StockBlockRtInfo> infos = parserStockInfoUtil.parse4StockBlock(result);
        log.info("板块数据量：{}",infos.size());
        System.out.println(infos);
        //将拉取到的数据分片,多线程插入到数据库中
        Lists.partition(infos,20).forEach(list->{
            threadPoolTaskExecutor.execute(()->{
                //20个一组，批量插入
                stockBlockRtInfoMapper.insertBatch(list);
            });
        });
    }
}
